Imports System.Drawing
Imports System.Drawing.Drawing2D
Imports System.Drawing.Graphics

Public Class FlexMapViewerC
    Inherits System.Windows.Forms.UserControl

#Region " Windows Form Designer generated code "

    Public Sub New()
        MyBase.New()

        'This call is required by the Windows Form Designer.
        InitializeComponent()

        'Add any initialization after the InitializeComponent() call

    End Sub

    'UserControl overrides dispose to clean up the component list.
    Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
        If disposing Then
            If Not (components Is Nothing) Then
                components.Dispose()
            End If
        End If
        MyBase.Dispose(disposing)
    End Sub

    'Required by the Windows Form Designer
    Private components As System.ComponentModel.IContainer

    'NOTE: The following procedure is required by the Windows Form Designer
    'It can be modified using the Windows Form Designer.  
    'Do not modify it using the code editor.
    Friend WithEvents pnlBorder As System.Windows.Forms.Panel
    Friend WithEvents txtX As System.Windows.Forms.TextBox
    Friend WithEvents txtY As System.Windows.Forms.TextBox
    Friend WithEvents txtZoom As System.Windows.Forms.TextBox
    Friend WithEvents lblCoordinates As System.Windows.Forms.Label
    Friend WithEvents lblZoom As System.Windows.Forms.Label
    Friend WithEvents picDisplay As System.Windows.Forms.PictureBox
    Friend WithEvents picTempBridge As System.Windows.Forms.PictureBox
    Friend WithEvents picSmallBridge As System.Windows.Forms.PictureBox
    Friend WithEvents picBridge As System.Windows.Forms.PictureBox
    Friend WithEvents picHeavyBridge As System.Windows.Forms.PictureBox
    Friend WithEvents tmrGeneral As System.Windows.Forms.Timer
    Friend WithEvents picVacantImage As System.Windows.Forms.PictureBox
    Friend WithEvents picBlankImage As System.Windows.Forms.PictureBox
    Friend WithEvents picBlast As System.Windows.Forms.PictureBox
    Friend WithEvents tmrReplay As System.Windows.Forms.Timer
    Friend WithEvents picFriendlyDead As System.Windows.Forms.PictureBox
    Friend WithEvents picEnemyDead As System.Windows.Forms.PictureBox
    Friend WithEvents picBlastMapSmall As System.Windows.Forms.PictureBox
    <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
        Me.components = New System.ComponentModel.Container
        Dim resources As System.ComponentModel.ComponentResourceManager = New System.ComponentModel.ComponentResourceManager(GetType(FlexMapViewerC))
        Me.pnlBorder = New System.Windows.Forms.Panel
        Me.picEnemyDead = New System.Windows.Forms.PictureBox
        Me.picFriendlyDead = New System.Windows.Forms.PictureBox
        Me.picBlast = New System.Windows.Forms.PictureBox
        Me.picBlankImage = New System.Windows.Forms.PictureBox
        Me.picVacantImage = New System.Windows.Forms.PictureBox
        Me.picBlastMapSmall = New System.Windows.Forms.PictureBox
        Me.picDisplay = New System.Windows.Forms.PictureBox
        Me.txtX = New System.Windows.Forms.TextBox
        Me.txtY = New System.Windows.Forms.TextBox
        Me.txtZoom = New System.Windows.Forms.TextBox
        Me.lblCoordinates = New System.Windows.Forms.Label
        Me.lblZoom = New System.Windows.Forms.Label
        Me.picTempBridge = New System.Windows.Forms.PictureBox
        Me.picSmallBridge = New System.Windows.Forms.PictureBox
        Me.picBridge = New System.Windows.Forms.PictureBox
        Me.picHeavyBridge = New System.Windows.Forms.PictureBox
        Me.tmrGeneral = New System.Windows.Forms.Timer(Me.components)
        Me.tmrReplay = New System.Windows.Forms.Timer(Me.components)
        Me.pnlBorder.SuspendLayout()
        CType(Me.picEnemyDead, System.ComponentModel.ISupportInitialize).BeginInit()
        CType(Me.picFriendlyDead, System.ComponentModel.ISupportInitialize).BeginInit()
        CType(Me.picBlast, System.ComponentModel.ISupportInitialize).BeginInit()
        CType(Me.picBlankImage, System.ComponentModel.ISupportInitialize).BeginInit()
        CType(Me.picVacantImage, System.ComponentModel.ISupportInitialize).BeginInit()
        CType(Me.picBlastMapSmall, System.ComponentModel.ISupportInitialize).BeginInit()
        CType(Me.picDisplay, System.ComponentModel.ISupportInitialize).BeginInit()
        CType(Me.picTempBridge, System.ComponentModel.ISupportInitialize).BeginInit()
        CType(Me.picSmallBridge, System.ComponentModel.ISupportInitialize).BeginInit()
        CType(Me.picBridge, System.ComponentModel.ISupportInitialize).BeginInit()
        CType(Me.picHeavyBridge, System.ComponentModel.ISupportInitialize).BeginInit()
        Me.SuspendLayout()
        '
        'pnlBorder
        '
        Me.pnlBorder.Anchor = CType((((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Bottom) _
                    Or System.Windows.Forms.AnchorStyles.Left) _
                    Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
        Me.pnlBorder.BackColor = System.Drawing.Color.Black
        Me.pnlBorder.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle
        Me.pnlBorder.Controls.Add(Me.picEnemyDead)
        Me.pnlBorder.Controls.Add(Me.picFriendlyDead)
        Me.pnlBorder.Controls.Add(Me.picBlast)
        Me.pnlBorder.Controls.Add(Me.picBlankImage)
        Me.pnlBorder.Controls.Add(Me.picVacantImage)
        Me.pnlBorder.Controls.Add(Me.picBlastMapSmall)
        Me.pnlBorder.Controls.Add(Me.picDisplay)
        Me.pnlBorder.Location = New System.Drawing.Point(0, 0)
        Me.pnlBorder.Name = "pnlBorder"
        Me.pnlBorder.Size = New System.Drawing.Size(464, 384)
        Me.pnlBorder.TabIndex = 3
        Me.pnlBorder.TabStop = True
        '
        'picEnemyDead
        '
        Me.picEnemyDead.Image = CType(resources.GetObject("picEnemyDead.Image"), System.Drawing.Image)
        Me.picEnemyDead.Location = New System.Drawing.Point(264, 288)
        Me.picEnemyDead.Name = "picEnemyDead"
        Me.picEnemyDead.Size = New System.Drawing.Size(25, 25)
        Me.picEnemyDead.TabIndex = 5
        Me.picEnemyDead.TabStop = False
        Me.picEnemyDead.Visible = False
        '
        'picFriendlyDead
        '
        Me.picFriendlyDead.Image = CType(resources.GetObject("picFriendlyDead.Image"), System.Drawing.Image)
        Me.picFriendlyDead.Location = New System.Drawing.Point(264, 256)
        Me.picFriendlyDead.Name = "picFriendlyDead"
        Me.picFriendlyDead.Size = New System.Drawing.Size(25, 26)
        Me.picFriendlyDead.TabIndex = 4
        Me.picFriendlyDead.TabStop = False
        Me.picFriendlyDead.Visible = False
        '
        'picBlast
        '
        Me.picBlast.Image = CType(resources.GetObject("picBlast.Image"), System.Drawing.Image)
        Me.picBlast.Location = New System.Drawing.Point(192, 240)
        Me.picBlast.Name = "picBlast"
        Me.picBlast.Size = New System.Drawing.Size(32, 32)
        Me.picBlast.TabIndex = 3
        Me.picBlast.TabStop = False
        Me.picBlast.Visible = False
        '
        'picBlankImage
        '
        Me.picBlankImage.Image = CType(resources.GetObject("picBlankImage.Image"), System.Drawing.Image)
        Me.picBlankImage.Location = New System.Drawing.Point(256, 184)
        Me.picBlankImage.Name = "picBlankImage"
        Me.picBlankImage.Size = New System.Drawing.Size(32, 32)
        Me.picBlankImage.TabIndex = 2
        Me.picBlankImage.TabStop = False
        Me.picBlankImage.Visible = False
        '
        'picVacantImage
        '
        Me.picVacantImage.Image = CType(resources.GetObject("picVacantImage.Image"), System.Drawing.Image)
        Me.picVacantImage.Location = New System.Drawing.Point(80, 136)
        Me.picVacantImage.Name = "picVacantImage"
        Me.picVacantImage.Size = New System.Drawing.Size(32, 32)
        Me.picVacantImage.TabIndex = 1
        Me.picVacantImage.TabStop = False
        Me.picVacantImage.Visible = False
        '
        'picBlastMapSmall
        '
        Me.picBlastMapSmall.Image = CType(resources.GetObject("picBlastMapSmall.Image"), System.Drawing.Image)
        Me.picBlastMapSmall.Location = New System.Drawing.Point(184, 208)
        Me.picBlastMapSmall.Name = "picBlastMapSmall"
        Me.picBlastMapSmall.Size = New System.Drawing.Size(16, 16)
        Me.picBlastMapSmall.TabIndex = 10
        Me.picBlastMapSmall.TabStop = False
        Me.picBlastMapSmall.Visible = False
        '
        'picDisplay
        '
        Me.picDisplay.Anchor = CType((((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Bottom) _
                    Or System.Windows.Forms.AnchorStyles.Left) _
                    Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
        Me.picDisplay.BackColor = System.Drawing.Color.Black
        Me.picDisplay.Location = New System.Drawing.Point(2, 2)
        Me.picDisplay.Name = "picDisplay"
        Me.picDisplay.Size = New System.Drawing.Size(458, 378)
        Me.picDisplay.TabIndex = 0
        Me.picDisplay.TabStop = False
        '
        'txtX
        '
        Me.txtX.Anchor = CType((System.Windows.Forms.AnchorStyles.Bottom Or System.Windows.Forms.AnchorStyles.Left), System.Windows.Forms.AnchorStyles)
        Me.txtX.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle
        Me.txtX.Location = New System.Drawing.Point(0, 360)
        Me.txtX.Name = "txtX"
        Me.txtX.ReadOnly = True
        Me.txtX.Size = New System.Drawing.Size(72, 22)
        Me.txtX.TabIndex = 0
        Me.txtX.Text = "0"
        Me.txtX.TextAlign = System.Windows.Forms.HorizontalAlignment.Center
        Me.txtX.Visible = False
        '
        'txtY
        '
        Me.txtY.Anchor = CType((System.Windows.Forms.AnchorStyles.Bottom Or System.Windows.Forms.AnchorStyles.Left), System.Windows.Forms.AnchorStyles)
        Me.txtY.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle
        Me.txtY.Location = New System.Drawing.Point(71, 360)
        Me.txtY.Name = "txtY"
        Me.txtY.ReadOnly = True
        Me.txtY.Size = New System.Drawing.Size(72, 22)
        Me.txtY.TabIndex = 1
        Me.txtY.Text = "0"
        Me.txtY.TextAlign = System.Windows.Forms.HorizontalAlignment.Center
        Me.txtY.Visible = False
        '
        'txtZoom
        '
        Me.txtZoom.Anchor = CType((System.Windows.Forms.AnchorStyles.Bottom Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
        Me.txtZoom.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle
        Me.txtZoom.Location = New System.Drawing.Point(384, 360)
        Me.txtZoom.Name = "txtZoom"
        Me.txtZoom.Size = New System.Drawing.Size(72, 22)
        Me.txtZoom.TabIndex = 2
        Me.txtZoom.Text = "100"
        Me.txtZoom.TextAlign = System.Windows.Forms.HorizontalAlignment.Center
        Me.txtZoom.Visible = False
        '
        'lblCoordinates
        '
        Me.lblCoordinates.Anchor = CType((System.Windows.Forms.AnchorStyles.Bottom Or System.Windows.Forms.AnchorStyles.Left), System.Windows.Forms.AnchorStyles)
        Me.lblCoordinates.Location = New System.Drawing.Point(152, 363)
        Me.lblCoordinates.Name = "lblCoordinates"
        Me.lblCoordinates.Size = New System.Drawing.Size(72, 16)
        Me.lblCoordinates.TabIndex = 4
        Me.lblCoordinates.Text = "Coordinates"
        Me.lblCoordinates.Visible = False
        '
        'lblZoom
        '
        Me.lblZoom.Anchor = CType((System.Windows.Forms.AnchorStyles.Bottom Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
        Me.lblZoom.Location = New System.Drawing.Point(336, 363)
        Me.lblZoom.Name = "lblZoom"
        Me.lblZoom.Size = New System.Drawing.Size(40, 16)
        Me.lblZoom.TabIndex = 5
        Me.lblZoom.Text = "Zoom"
        Me.lblZoom.TextAlign = System.Drawing.ContentAlignment.MiddleRight
        Me.lblZoom.Visible = False
        '
        'picTempBridge
        '
        Me.picTempBridge.Image = CType(resources.GetObject("picTempBridge.Image"), System.Drawing.Image)
        Me.picTempBridge.Location = New System.Drawing.Point(240, 328)
        Me.picTempBridge.Name = "picTempBridge"
        Me.picTempBridge.Size = New System.Drawing.Size(16, 16)
        Me.picTempBridge.TabIndex = 6
        Me.picTempBridge.TabStop = False
        '
        'picSmallBridge
        '
        Me.picSmallBridge.Image = CType(resources.GetObject("picSmallBridge.Image"), System.Drawing.Image)
        Me.picSmallBridge.Location = New System.Drawing.Point(264, 328)
        Me.picSmallBridge.Name = "picSmallBridge"
        Me.picSmallBridge.Size = New System.Drawing.Size(16, 16)
        Me.picSmallBridge.TabIndex = 7
        Me.picSmallBridge.TabStop = False
        '
        'picBridge
        '
        Me.picBridge.Image = CType(resources.GetObject("picBridge.Image"), System.Drawing.Image)
        Me.picBridge.Location = New System.Drawing.Point(288, 328)
        Me.picBridge.Name = "picBridge"
        Me.picBridge.Size = New System.Drawing.Size(16, 16)
        Me.picBridge.TabIndex = 8
        Me.picBridge.TabStop = False
        '
        'picHeavyBridge
        '
        Me.picHeavyBridge.Image = CType(resources.GetObject("picHeavyBridge.Image"), System.Drawing.Image)
        Me.picHeavyBridge.Location = New System.Drawing.Point(312, 328)
        Me.picHeavyBridge.Name = "picHeavyBridge"
        Me.picHeavyBridge.Size = New System.Drawing.Size(16, 16)
        Me.picHeavyBridge.TabIndex = 9
        Me.picHeavyBridge.TabStop = False
        '
        'tmrGeneral
        '
        Me.tmrGeneral.Interval = 10
        '
        'tmrReplay
        '
        Me.tmrReplay.Interval = 1000
        '
        'FlexMapViewerC
        '
        Me.Controls.Add(Me.pnlBorder)
        Me.Controls.Add(Me.lblZoom)
        Me.Controls.Add(Me.lblCoordinates)
        Me.Controls.Add(Me.txtZoom)
        Me.Controls.Add(Me.txtY)
        Me.Controls.Add(Me.txtX)
        Me.Controls.Add(Me.picHeavyBridge)
        Me.Controls.Add(Me.picBridge)
        Me.Controls.Add(Me.picSmallBridge)
        Me.Controls.Add(Me.picTempBridge)
        Me.Font = New System.Drawing.Font("Microsoft Sans Serif", 9.75!, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, CType(0, Byte))
        Me.Name = "FlexMapViewerC"
        Me.Size = New System.Drawing.Size(464, 384)
        Me.pnlBorder.ResumeLayout(False)
        CType(Me.picEnemyDead, System.ComponentModel.ISupportInitialize).EndInit()
        CType(Me.picFriendlyDead, System.ComponentModel.ISupportInitialize).EndInit()
        CType(Me.picBlast, System.ComponentModel.ISupportInitialize).EndInit()
        CType(Me.picBlankImage, System.ComponentModel.ISupportInitialize).EndInit()
        CType(Me.picVacantImage, System.ComponentModel.ISupportInitialize).EndInit()
        CType(Me.picBlastMapSmall, System.ComponentModel.ISupportInitialize).EndInit()
        CType(Me.picDisplay, System.ComponentModel.ISupportInitialize).EndInit()
        CType(Me.picTempBridge, System.ComponentModel.ISupportInitialize).EndInit()
        CType(Me.picSmallBridge, System.ComponentModel.ISupportInitialize).EndInit()
        CType(Me.picBridge, System.ComponentModel.ISupportInitialize).EndInit()
        CType(Me.picHeavyBridge, System.ComponentModel.ISupportInitialize).EndInit()
        Me.ResumeLayout(False)
        Me.PerformLayout()

    End Sub

#End Region

    Public Event DisplayClick(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs)
    Public Event MapScroll()
    Public Event Rendered()
    Public Event UndoRequest()
    Public Event EnterPressed()
    Public Event BackspacePressed()
    Public Event FKeyPressed(ByVal keyName As String)
    Public Event DisplayMouseMove(ByVal e As System.Windows.Forms.MouseEventArgs)
    Public Event DisplayMouseDown(ByVal e As System.Windows.Forms.MouseEventArgs)

    Private c_Module As String = "FlexMapViewerC"
    Private c_DefaultVertexSize As Int16 = 3
    Private c_SelectionColor As Color = Color.Yellow
    Private c_MinimumZoom As Single = 0.01
    Private c_MaximumZoom As Single = 5.0

    ' zoom is going to wait a while I think.
    Private zoom As Single       '0.01 to 2.0: 1% to 500%

    ' property variables
    Private m_ZoomFactor As Single = 1
    Private m_OffsetX As Integer
    Private m_OffsetY As Integer
    Private m_Rendered As Boolean
    Private m_BMP As Bitmap   ' a bmp of our map, in its edited mode
    Private m_FMP As New FMPLib01.FlexMapData()
    Private m_Map As Image
    Private m_WaypointColor As System.Drawing.Color = Color.Beige
    Private m_FeaturePathOutlineColor As System.Drawing.Color = Color.Yellow
    Private m_VertexColor As System.Drawing.Color = Color.AntiqueWhite
    Private m_VertexSize As Int16 = c_DefaultVertexSize
    Private m_showPaths As Boolean = False
    Private m_showGrid As Boolean = False
    Private m_showScale As Boolean = False
    Private m_showLabels As Boolean = True
    Private m_labelColor As Color = Color.Yellow
    Private m_labelSize As Int16 = 16
    Private m_selectedBridge As FMPLib01.FlexMapData.Bridge
    Private m_bridgeSelected As Boolean = False
    Private m_selectionColor As Color = c_SelectionColor
    Friend m_MapOpened As Boolean = False
    Private m_ScrollDistance As Integer = 40

    Friend bEditable As Boolean = False


#Region "picDisplay Events"
    Private Sub picDisplay_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles picDisplay.MouseUp
        Dim j As New System.Windows.Forms.MouseEventArgs(e.Button, e.Clicks, e.X - m_OffsetX, e.Y - m_OffsetY, e.Delta)

        RaiseEvent DisplayClick(sender, j)
    End Sub

    Private Sub picDisplay_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles picDisplay.MouseMove
        Dim j As New System.Windows.Forms.MouseEventArgs(e.Button, e.Clicks, e.X - m_OffsetX, e.Y - m_OffsetY, e.Delta)

        RaiseEvent DisplayMouseMove(j)
    End Sub

    Private Sub picDisplay_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles picDisplay.MouseDown
        Dim j As New System.Windows.Forms.MouseEventArgs(e.Button, e.Clicks, e.X - m_OffsetX, e.Y - m_OffsetY, e.Delta)

        RaiseEvent DisplayMouseDown(j)
    End Sub
#End Region

#Region "Map Redraw and Position"

    Public Sub ResetPosition()
        ' resets zoom and offsets
        m_OffsetX = 0
        m_OffsetY = 0
        m_ZoomFactor = 1
        RedrawMap()
    End Sub

    Public Sub RedrawMap()
        RenderToDisplay()
        SetPosition()
    End Sub

    Overridable Sub RenderToDisplay()
        If Not m_FMP Is Nothing Then
            If m_Rendered = False Then Exit Sub
            Dim width As Int16 = m_FMP.Width * m_ZoomFactor
            Dim height As Int16 = m_FMP.Height * m_ZoomFactor
            Dim im As Image = New Bitmap(width, height)
            Dim g As Graphics = Graphics.FromImage(im)

            Dim tickStart As Date
            Dim tickstop As Date

            Dim RenderTickCount As Int64

            ' if this is the first time rendering this map, then procede as normal. If we are redrawing the map
            ' then we should set the basebmp

            tickStart = Now
            ' if we are editable, then each render is a hardrender
            If bEditable = True Then
                m_FMP.Render(g, g.VisibleClipBounds, m_showPaths, , m_ZoomFactor, m_ZoomFactor)
            Else
                If m_MapOpened = True Then
                    m_FMP.Render(g, g.VisibleClipBounds, m_showPaths, , m_ZoomFactor, m_ZoomFactor, , , , False)
                Else
                    m_FMP.Render(g, g.VisibleClipBounds, m_showPaths, , m_ZoomFactor, m_ZoomFactor)
                End If
            End If
            tickstop = Now
            RenderTickCount = tickstop.Ticks - tickStart.Ticks

            'add bridges and labels
            DrawRoads(g)
            DrawBridges(g)
            DrawLabels(g)

            picDisplay.Image = im
            m_BMP = im

            SetPosition()

            g.Dispose()
            GC.Collect()

            m_Rendered = True
            RaiseEvent Rendered()

        End If
    End Sub

    Protected Sub SetPosition()
        ' used for scrolling
        'If picDisplay.Image Is Nothing Then
        '    OffSetX = 0
        '    OffSetY = 0
        '    Exit Sub
        'End If

        '' set the offsets equal to themselves to reset for max 
        'OffSetX = m_OffsetX

        'If m_Rendered = False Then Exit Sub
        '' apply zooming
        'Dim im As Image = New Bitmap(CInt(m_FMP.Width * ZoomFactor), CInt(m_FMP.Height * ZoomFactor))
        'Dim g As Graphics = Graphics.FromImage(im)

        'Try
        '    g.DrawImage(m_BMP, OffSetX, OffSetY)
        '    picDisplay.Image = im.Clone
        '    g.Dispose()
        '    im.Dispose()
        '    GC.Collect()
        'Catch ex As Exception
        '    HandleException(c_Module, ex)
        'End Try

        If Me.Width > picDisplay.Width Then
            picDisplay.Left = 0
        End If

        If Me.Height > picDisplay.Height Then
            picDisplay.Top = 0
        End If

        RaiseEvent MapScroll()

    End Sub
#End Region

#Region "Supporting Map: Labels, Bridges"

    Protected Sub DrawRoads(ByRef g As Graphics)
        Dim aroad As FMPLib01.Road
        Dim sp As New Pen(Color.Brown, 2)
        Dim spborder As New Pen(Color.Black, 4)

        If m_FMP.Roads Is Nothing Then m_FMP.Roads = New FMPLib01.Roads

        g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias
        For Each aroad In m_FMP.Roads
            If aroad.RoadType = FMPLib01.FlexMapData.RoadType.MajorRoad Then
                sp.Width = 1
                spborder.Width = 5
                sp.Color = Color.Yellow
                spborder.Color = Color.Black
            Else
                sp.Width = 2
                spborder.Width = 4
                sp.Color = Color.Brown
                spborder.Color = Color.Black
            End If
            g.DrawLine(spborder, aroad.StartPoint, aroad.EndPoint)
            g.DrawLine(sp, aroad.StartPoint, aroad.EndPoint)
        Next
        g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighSpeed
        sp.Dispose()
        spborder.Dispose()

    End Sub

    Overridable Sub DrawLabels(ByVal g As Graphics)
        If m_showLabels = False Then Exit Sub

        Dim lab As FMPLib01.FlexMapData.MapLabel
        Dim fnt As New Font("arial", m_labelSize)
        Dim br As New SolidBrush(m_labelColor)

        Try
            For Each lab In FMPData.Labels
                Dim pth As New GraphicsPath
                Dim pnt As New PointF(lab.x, lab.y)

                pth.AddString(lab.text, System.Drawing.FontFamily.GenericSerif, System.Drawing.FontStyle.Regular, m_labelSize, pnt, System.Drawing.StringFormat.GenericDefault)

                Dim bounds As RectangleF = pth.GetBounds
                Dim boundsBrush As New SolidBrush(lab.backgroundColor)
                ' increase the size of the box by 1 pixel all the way around
                bounds.X -= 1
                bounds.Y -= 1
                bounds.Width += 3
                bounds.Height += 3

                ' do the markbox. The markbox is a square around the actual position of the label, its basically an arrow.
                Dim markBoxSolid As New RectangleF(bounds.X - 3, bounds.Y - 3, 6, 6)
                Dim markBrush As New SolidBrush(Color.Red)
                Dim markBoxBounds As New Rectangle(markBoxSolid.X, markBoxSolid.Y, markBoxSolid.Width, markBoxSolid.Height)
                g.FillRectangle(markBrush, markBoxSolid)
                g.DrawRectangle(Pens.Black, markBoxBounds)
                markBrush.Dispose()

                Dim boundsBox As New Rectangle(bounds.X, bounds.Y, bounds.Width, bounds.Height)
                g.FillRectangle(boundsBrush, bounds)
                g.DrawRectangle(Pens.Black, boundsBox)
                boundsBrush.Dispose()

                Dim textBrush As New SolidBrush(lab.foreColor)
                'br.Color = lab.foreColor
                g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias
                g.FillPath(textBrush, pth)
                g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.Default
                textBrush.Dispose()
                DrawTemporaryLabels(g)
            Next

        Catch ex As Exception
            HandleException(c_Module, ex)
        End Try

    End Sub

    Private Sub DrawTemporaryLabels(ByVal g As Graphics)
        ' this is used so we can totally draw the really cool labels that are in a CGD file and not stored in the map. Its cool.
        ' trust me.
        Dim lab As FMPLib01.FlexMapData.MapLabel
        Dim fnt As New Font("arial", m_labelSize)
        Dim br As New SolidBrush(m_labelColor)

        Try
            For Each lab In FMPData.TemporaryLabels
                Dim pth As New GraphicsPath
                Dim pnt As New PointF(lab.x, lab.y)

                pth.AddString(lab.text, System.Drawing.FontFamily.GenericSerif, System.Drawing.FontStyle.Regular, m_labelSize, pnt, System.Drawing.StringFormat.GenericDefault)

                Dim bounds As RectangleF = pth.GetBounds
                Dim boundsBrush As New SolidBrush(lab.backgroundColor)
                ' increase the size of the box by 1 pixel all the way around
                bounds.X -= 1
                bounds.Y -= 1
                bounds.Width += 3
                bounds.Height += 3

                ' do the markbox. The markbox is a square around the actual position of the label, its basically an arrow.
                Dim markBoxSolid As New RectangleF(bounds.X - 3, bounds.Y - 3, 6, 6)
                Dim markBrush As New SolidBrush(Color.Red)
                Dim markBoxBounds As New Rectangle(markBoxSolid.X, markBoxSolid.Y, markBoxSolid.Width, markBoxSolid.Height)
                g.FillRectangle(markBrush, markBoxSolid)
                g.DrawRectangle(Pens.Black, markBoxBounds)
                markBrush.Dispose()

                Dim boundsBox As New Rectangle(bounds.X, bounds.Y, bounds.Width, bounds.Height)
                g.FillRectangle(boundsBrush, bounds)
                g.DrawRectangle(Pens.Black, boundsBox)
                boundsBrush.Dispose()

                Dim textBrush As New SolidBrush(lab.foreColor)
                'br.Color = lab.foreColor
                g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias
                g.FillPath(textBrush, pth)
                g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.Default
                textBrush.Dispose()

            Next
        Catch ex As Exception
            HandleException(c_Module, ex)
        End Try
    End Sub

    Overridable Sub DrawBridges(ByVal g As Graphics)
        Dim bri As FMPLib01.FlexMapData.Bridge

        Try
            For Each bri In FMPData.Bridges
                Dim bmp As Bitmap
                Dim bridgeCoord As PointF = New PointF(bri.x, bri.y)

                Select Case bri.type
                    Case FMPLib01.FlexMapData.BridgeType.temporaryBridge
                        bmp = picTempBridge.Image
                    Case FMPLib01.FlexMapData.BridgeType.smallBridge
                        bmp = picSmallBridge.Image
                    Case FMPLib01.FlexMapData.BridgeType.mediumBridge
                        bmp = picBridge.Image
                    Case FMPLib01.FlexMapData.BridgeType.heavyBridge
                        bmp = picHeavyBridge.Image
                End Select
                bmp.MakeTransparent(Color.FromArgb(255, 0, 255))
                bridgeCoord.x -= bmp.Width / 2
                bridgeCoord.y -= bmp.Height / 2
                ' check for selection first
                If BridgeSelected Then
                    If SelectedBridge.Equals(bri) Then
                        ' draw a yellow splotch where the bridge will go (of course and a little bigger)
                        Dim selBrush As New SolidBrush(m_selectionColor)
                        Dim modLocation As New PointF(bridgeCoord.x - 3, bridgeCoord.y - 3)
                        g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias
                        g.FillEllipse(selBrush, modLocation.X, modLocation.Y, bmp.Width + 5, bmp.Height + 5)
                        g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.Default
                    End If
                End If
                ' draw the bridge
                g.DrawImage(bmp, bridgeCoord.x, bridgeCoord.y)
            Next
        Catch ex As Exception
            HandleException(c_Module, ex)
        End Try

    End Sub

    Overridable Sub DrawScale(ByRef g As Graphics)
        If m_showScale = False Then Exit Sub
        Try
            Dim scaleLineStart As New Point(40, 40)
            Dim scaleLineEnd As New Point(FMPData.MapScale.PixelCount + 40, 40)
            Dim scaleLinePen As New Pen(Color.Yellow, 4)
            Dim rect As New RectangleF(30, 30, (scaleLineEnd.X - 20), 30)

            If rect.Width < 60 Then rect.Width = 60
            Dim rectBrush As New SolidBrush(Color.FromArgb(100, 0, 0, 0))
            Dim miles As Integer = FMPData.MapScale.MilesPerPixelCount
            Dim milesText As String
            If miles < 2 Then
                milesText = " mile"
            Else
                milesText = " miles"
            End If
            g.FillRectangle(rectBrush, rect)
            g.DrawRectangle(Pens.Black, New Rectangle(rect.X, rect.Y, rect.Width, rect.Height))
            g.DrawLine(scaleLinePen, scaleLineStart, scaleLineEnd)
            g.DrawString(miles & milesText, Me.Font, Brushes.Yellow, 45, 45)

        Catch ex As Exception
            HandleException(c_Module, ex)
        End Try
    End Sub

    Public Overridable Sub DrawGrid(ByRef g As Graphics)
        If m_showGrid = False Then Exit Sub

        Try
            Dim x As Integer
            Dim y As Integer
            Dim stepCounter As Integer = 0 ' just before the first letter character in the ascii codes
            Dim f As New Font(Me.Font.FontFamily, 12, FontStyle.Bold)

            Dim fatterpen As New Pen(Color.FromArgb(100, 210, 210, 210), 3)

            For x = 1 To FMPData.Width Step FMPData.MapScale.PixelCount
                ' draw the vertical lines
                g.DrawLine(fatterpen, x, 0, x, FMPData.Height)
                g.DrawLine(Pens.DarkBlue, x, 0, x, FMPData.Height)
                ' draw a grid identifier
                g.DrawString(stepCounter, f, Brushes.DarkBlue, x - (FMPData.MapScale.PixelCount / 2), 10)
                stepCounter += 1
            Next

            stepCounter = 0

            For y = 1 To FMPData.Height Step FMPData.MapScale.PixelCount
                ' draw a line for the grid
                g.DrawLine(fatterpen, 0, y, FMPData.Width, y)
                g.DrawLine(Pens.DarkBlue, 0, y, FMPData.Width, y)
                ' draw grid identifier
                g.DrawString(stepCounter, f, Brushes.DarkBlue, 10, y - (FMPData.MapScale.PixelCount / 2))
                stepCounter += 1
            Next

        Catch ex As Exception
            HandleException(c_Module, ex)
        End Try

    End Sub
#End Region

#Region "Key Pressing"
    Protected Overrides Function ProcessDialogKey(ByVal keyData As System.Windows.Forms.Keys) As Boolean
        If ActiveControl Is pnlBorder Then
            ' ignore arrows

            Select Case keyData
                Case Keys.Left
                    Dim newLoc As New Point(picDisplay.Location.X + m_ScrollDistance, picDisplay.Location.Y)
                    picDisplay.Location = newLoc
                    'OffSetX += m_ScrollDistance * ZoomFactor
                    SetPosition()
                    Return True
                Case Keys.Right
                    Dim newLoc As New Point(picDisplay.Location.X - m_ScrollDistance, picDisplay.Location.Y)
                    picDisplay.Location = newLoc
                    'OffSetX -= m_ScrollDistance * ZoomFactor
                    SetPosition()
                    Return True
                Case Keys.Down
                    Dim newLoc As New Point(picDisplay.Location.X, picDisplay.Location.Y - m_ScrollDistance)
                    picDisplay.Location = newLoc
                    'OffSetY -= m_ScrollDistance * ZoomFactor
                    SetPosition()
                    Return True
                Case Keys.Up
                    Dim newLoc As New Point(picDisplay.Location.X, picDisplay.Location.Y + m_ScrollDistance)
                    picDisplay.Location = newLoc
                    'OffSetY += m_ScrollDistance * ZoomFactor
                    SetPosition()
                    Return True
                Case Keys.Add
                    'TASK: Zooming
                    ZoomFactor += 0.1
                    SetPosition()
                Case Keys.Subtract
                    ZoomFactor -= 0.1
                    SetPosition()
                Case Keys.Tab
                    ' tabbing out of the panel
                    pnlBorder.BackColor = System.Drawing.Color.Black
                Case Keys.Enter
                    RaiseEvent EnterPressed()
                Case Keys.Back
                    RaiseEvent BackspacePressed()
                Case Keys.F12
                    RaiseEvent FKeyPressed("F12")
            End Select

        Else
            ' we are not currently the active control.
            pnlBorder.BackColor = System.Drawing.Color.Black
        End If

        If ActiveControl Is txtZoom Then
            If keyData = Keys.Tab Then
                ' since tab was used to get here, lets change the border color to gold.
                pnlBorder.BackColor = System.Drawing.Color.Gold
                pnlBorder.Select()
                Return True
            End If

        End If

        ' catch shift+tab
        If ActiveControl Is txtX Then
            If (keyData.ToString = "Tab, Shift") Then
                pnlBorder.BackColor = System.Drawing.Color.Gold
                pnlBorder.Select()
                Return True
            End If
        End If

        ' handles anything else
        Return MyBase.ProcessDialogKey(keyData)
    End Function

    Private Sub pnlBorder_Click(ByVal sender As Object, ByVal e As EventArgs) Handles pnlBorder.Click
        pnlBorder.BackColor = System.Drawing.Color.Gold
        pnlBorder.Select()
    End Sub

    Private Sub picDisplay_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles picDisplay.Click
        pnlBorder.BackColor = System.Drawing.Color.Gold
        pnlBorder.Focus()
        pnlBorder.Select()

    End Sub


    Private Sub pnlBorder_Validating(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles pnlBorder.Validating
        pnlBorder.BackColor = System.Drawing.Color.Black
    End Sub
#End Region

#Region "Additional Drawing, FeaturePath, Vertex"
    Friend Sub DrawFeaturePath(ByVal gPath As GraphicsPath, ByVal pathCol As Color, ByVal vertexColor As Color, ByVal vertexSize As Int16)
        Dim g As Graphics

        Try
            Dim pnt As PointF
            Dim penman As New Pen(pathCol)
            g = picDisplay.CreateGraphics
            g.TranslateTransform(OffSetX, OffSetY)
            g.DrawPath(penman, gPath)
            ' draw vertices
            penman.Color = vertexColor

            For Each pnt In gPath.PathPoints
                DrawVertex(g, pnt, vertexSize, vertexColor)
            Next
            g.Dispose()
        Catch ex As ArgumentException
            Exit Sub
        Catch ex As Exception
            HandleException(c_Module, ex)
        End Try
    End Sub

    Public Sub DrawFeaturePath(ByVal gPath As GraphicsPath)
        ' a featurepath is a shape drawn on the map representing a certain type of terrain.
        ' this is the default method, provided to use the property values
        DrawFeaturePath(gPath, m_FeaturePathOutlineColor, m_VertexColor, m_VertexSize)

    End Sub

    Public Sub DrawVertex(ByVal g As Graphics, ByVal pnt As PointF, ByVal vertexSize As Int16, ByVal vertexColor As Color)
        Dim penman As New Pen(vertexColor)
        g.DrawRectangle(penman, CType((pnt.X - vertexSize / 2), Single), CType(pnt.Y - (vertexSize / 2), Single), vertexSize, vertexSize)
    End Sub
#End Region

#Region "Properties"

    Public Property showScale() As Boolean
        Get
            Return m_showScale
        End Get
        Set(ByVal Value As Boolean)
            m_showScale = Value
        End Set
    End Property

    Public Property showGrid() As Boolean
        Get
            Return m_showGrid
        End Get
        Set(ByVal Value As Boolean)
            m_showGrid = Value
        End Set
    End Property

    Public Property ZoomFactor() As Single
        Get
            Return m_ZoomFactor
        End Get
        Set(ByVal Value As Single)
            If Value > c_MaximumZoom Then
                Value = c_MaximumZoom
            End If
            If Value < c_MinimumZoom Then
                Value = c_MinimumZoom
            End If
            m_ZoomFactor = Value
            SetPosition()
            RedrawMap()
        End Set
    End Property


    Public Property BridgeSelected() As Boolean
        Get
            Return m_bridgeSelected
        End Get
        Set(ByVal Value As Boolean)
            m_bridgeSelected = Value
        End Set
    End Property

    Public Property SelectedBridge() As FMPLib01.FlexMapData.Bridge
        Get
            ' this is used to pass around the selected bridge, but also to select one from outside (like... from a listbox, no?)
            Return m_selectedBridge
        End Get
        Set(ByVal Value As FMPLib01.FlexMapData.Bridge)
            m_selectedBridge = Value
            If m_selectedBridge Is Nothing Then
                m_bridgeSelected = False
            Else
                m_bridgeSelected = True
            End If
            ' if we provided a selected bridge, we must redraw the map
            RedrawMap()
        End Set
    End Property

    Public Property LabelSize() As Int16
        Get
            Return m_labelSize
        End Get
        Set(ByVal Value As Int16)
            m_labelSize = Value
        End Set
    End Property

    Public Property LabelColor() As Color
        Get
            Return m_labelColor
        End Get
        Set(ByVal Value As Color)
            m_labelColor = Value
        End Set
    End Property

    Public Property ShowLabels() As Boolean
        Get
            Return m_showLabels
        End Get
        Set(ByVal Value As Boolean)
            m_showLabels = Value
            RedrawMap()
        End Set
    End Property

    Public Property ShowPaths() As Boolean
        Get
            Return m_showPaths
        End Get
        Set(ByVal Value As Boolean)
            m_showPaths = Value
            RedrawMap()
        End Set
    End Property

    Protected ReadOnly Property FMP() As FMPLib01.FlexMapData
        Get
            Return m_FMP
        End Get

    End Property

    Protected Property Rendered_b() As Boolean
        Get
            Return m_Rendered
        End Get
        Set(ByVal Value As Boolean)
            m_Rendered = Value
        End Set
    End Property

    Protected Property BMP() As Bitmap
        Get
            Return m_BMP
        End Get
        Set(ByVal Value As Bitmap)
            m_BMP = Value
        End Set
    End Property

    Friend Property OffSetX() As Integer
        Get
            Return m_OffsetX
        End Get
        Set(ByVal Value As Integer)
            m_OffsetX = Value
            SetMaxScroll()
        End Set
    End Property

    Friend Property OffSetY() As Int16
        Get
            Return m_OffsetY
        End Get
        Set(ByVal Value As Int16)
            m_OffsetY = Value
            SetMaxScroll()
        End Set

    End Property

    Public Property FMPData() As FMPLib01.FlexMapData
        Get
            Return m_FMP
        End Get
        Set(ByVal Value As FMPLib01.FlexMapData)
            If Value Is Nothing Then Exit Property

            m_FMP = Value
            m_BMP = New Bitmap(m_FMP.Width, m_FMP.Height)
            m_Rendered = True
            RenderToDisplay()
        End Set
    End Property

    Public Property FeaturePathOutlineColor() As Color
        Get
            Return m_FeaturePathOutlineColor
        End Get
        Set(ByVal Value As Color)
            m_FeaturePathOutlineColor = Value
        End Set
    End Property

    Public Property VertexColor() As Color
        Get
            Return m_VertexColor
        End Get
        Set(ByVal Value As Color)
            m_VertexColor = Value
        End Set
    End Property

    Public Property VertexSize() As Int16
        Get
            Return m_VertexSize
        End Get
        Set(ByVal Value As Int16)
            m_VertexSize = Value
        End Set
    End Property

    Public ReadOnly Property MapBitmap() As Bitmap
        Get
            Return m_BMP
        End Get
    End Property

    Public Property MapOpened() As Boolean
        Get
            Return m_MapOpened
        End Get
        Set(ByVal Value As Boolean)
            m_MapOpened = Value
        End Set
    End Property

#End Region

    Public Sub SaveBMP()
        m_BMP.Save("c:\Map.jpg", Imaging.ImageFormat.Jpeg)
    End Sub

    Public Sub OpenMap(ByVal filePath As String)
        ' this sets up our beloved map.
        m_FMP = New FMPLib01.FlexMapData
        m_FMP = m_FMP.OpenMap(filePath)
        m_BMP = New Bitmap(m_FMP.Width, m_FMP.Height)
        m_Rendered = True

        picDisplay.Width = m_FMP.Width
        picDisplay.Height = m_FMP.Height

        RenderToDisplay()
        m_MapOpened = True
    End Sub

    Private Sub FlexMapViewerC_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        pnlBorder.Select()
    End Sub

    Public Sub DrawScaledMap(ByVal g As Graphics)
        Try
            g.DrawImage(m_BMP, g.VisibleClipBounds)
        Catch ex As Exception

        End Try
    End Sub

    Overridable Sub SetMaxScroll()
        If m_Rendered = False Then
            m_OffsetX = 0
            m_OffsetY = 0
            Exit Sub
        End If

        ' set maximum scrolling
        If m_OffsetX > 0 Then m_OffsetX = 0
        If m_OffsetY > 0 Then m_OffsetY = 0

        'If m_OffsetX < -1 * (CInt(m_FMP.Width * ZoomFactor) - picDisplay.Width) Then
        '    m_OffsetX = -1 * (CInt(m_FMP.Width * ZoomFactor) - picDisplay.Width)
        'End If

        If m_OffsetX / ZoomFactor < -1 * (CInt(m_FMP.Width) - picDisplay.Width) * ZoomFactor Then
            m_OffsetX = -1 * (CInt(m_FMP.Width) - picDisplay.Width) * ZoomFactor * ZoomFactor
        End If

        If m_OffsetY < -1 * (CInt(m_FMP.Height * ZoomFactor) - picDisplay.Height) Then
            m_OffsetY = -1 * (CInt(m_FMP.Height * ZoomFactor) - picDisplay.Height)
        End If

        ' catch for display being larger than map height and width
        If picDisplay.Width > (m_FMP.Width * ZoomFactor) Then m_OffsetX = 0
        If picDisplay.Height > (m_FMP.Height * ZoomFactor) Then m_OffsetY = 0
    End Sub

    Private Sub pnlBorder_Layout(ByVal sender As Object, ByVal e As System.Windows.Forms.LayoutEventArgs) Handles pnlBorder.Layout
        pnlBorder.BackColor = Color.Black
    End Sub

End Class
